From 7291860737650923de83f142e88874463b041da7 Mon Sep 17 00:00:00 2001 From: Eddie Dong Date: Thu, 9 Jun 2011 16:24:09 +0800 Subject: [PATCH] Nested VMX: Extend VMCS control fields for n2 guest Signed-off-by: Qing He Signed-off-by: Eddie Dong Signed-off-by: Tim Deegan Committed-by: Tim Deegan --- xen/arch/x86/hvm/vmx/vmx.c | 19 +++++-- xen/arch/x86/hvm/vmx/vvmx.c | 86 ++++++++++++++++++++++++++++++ xen/include/asm-x86/hvm/vmx/vvmx.h | 5 ++ 3 files changed, 106 insertions(+), 4 deletions(-) diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index 169a5ce0d1..214c711b34 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -54,6 +54,7 @@ #include #include #include +#include enum handler_return { HNDL_done, HNDL_unhandled, HNDL_exception_raised }; @@ -361,18 +362,28 @@ long_mode_do_msr_write(unsigned int msr, uint64_t msr_content) void vmx_update_cpu_exec_control(struct vcpu *v) { - __vmwrite(CPU_BASED_VM_EXEC_CONTROL, v->arch.hvm_vmx.exec_control); + if ( nestedhvm_vcpu_in_guestmode(v) ) + nvmx_update_exec_control(v, v->arch.hvm_vmx.exec_control); + else + __vmwrite(CPU_BASED_VM_EXEC_CONTROL, v->arch.hvm_vmx.exec_control); } static void vmx_update_secondary_exec_control(struct vcpu *v) { - __vmwrite(SECONDARY_VM_EXEC_CONTROL, - v->arch.hvm_vmx.secondary_exec_control); + if ( nestedhvm_vcpu_in_guestmode(v) ) + nvmx_update_secondary_exec_control(v, + v->arch.hvm_vmx.secondary_exec_control); + else + __vmwrite(SECONDARY_VM_EXEC_CONTROL, + v->arch.hvm_vmx.secondary_exec_control); } void vmx_update_exception_bitmap(struct vcpu *v) { - __vmwrite(EXCEPTION_BITMAP, v->arch.hvm_vmx.exception_bitmap); + if ( nestedhvm_vcpu_in_guestmode(v) ) + nvmx_update_exception_bitmap(v, v->arch.hvm_vmx.exception_bitmap); + else + __vmwrite(EXCEPTION_BITMAP, v->arch.hvm_vmx.exception_bitmap); } static int vmx_guest_x86_mode(struct vcpu *v) diff --git a/xen/arch/x86/hvm/vmx/vvmx.c b/xen/arch/x86/hvm/vmx/vvmx.c index 1847339631..dd9f308c24 100644 --- a/xen/arch/x86/hvm/vmx/vvmx.c +++ b/xen/arch/x86/hvm/vmx/vvmx.c @@ -25,6 +25,7 @@ #include #include #include +#include static void nvmx_purge_vvmcs(struct vcpu *v); @@ -392,6 +393,91 @@ static void vmreturn(struct cpu_user_regs *regs, enum vmx_ops_result ops_res) regs->eflags = eflags; } +/* + * Nested VMX uses "strict" condition to exit from + * L2 guest if either L1 VMM or L0 VMM expect to exit. + */ +static inline u32 __shadow_control(struct vcpu *v, + unsigned int field, + u32 host_value) +{ + struct nestedvcpu *nvcpu = &vcpu_nestedhvm(v); + + return (u32) __get_vvmcs(nvcpu->nv_vvmcx, field) | host_value; +} + +static void set_shadow_control(struct vcpu *v, + unsigned int field, + u32 host_value) +{ + __vmwrite(field, __shadow_control(v, field, host_value)); +} + +unsigned long *_shadow_io_bitmap(struct vcpu *v) +{ + struct nestedvmx *nvmx = &vcpu_2_nvmx(v); + int port80, portED; + u8 *bitmap; + + bitmap = nvmx->iobitmap[0]; + port80 = bitmap[0x80 >> 3] & (1 << (0x80 & 0x7)) ? 1 : 0; + portED = bitmap[0xed >> 3] & (1 << (0xed & 0x7)) ? 1 : 0; + + return nestedhvm_vcpu_iomap_get(port80, portED); +} + +void nvmx_update_exec_control(struct vcpu *v, u32 host_cntrl) +{ + u32 pio_cntrl = (CPU_BASED_ACTIVATE_IO_BITMAP + | CPU_BASED_UNCOND_IO_EXITING); + unsigned long *bitmap; + u32 shadow_cntrl; + + shadow_cntrl = __n2_exec_control(v); + pio_cntrl &= shadow_cntrl; + /* Enforce the removed features */ + shadow_cntrl &= ~(CPU_BASED_TPR_SHADOW + | CPU_BASED_ACTIVATE_MSR_BITMAP + | CPU_BASED_ACTIVATE_SECONDARY_CONTROLS + | CPU_BASED_ACTIVATE_IO_BITMAP + | CPU_BASED_UNCOND_IO_EXITING); + shadow_cntrl |= host_cntrl; + if ( pio_cntrl == CPU_BASED_UNCOND_IO_EXITING ) { + /* L1 VMM intercepts all I/O instructions */ + shadow_cntrl |= CPU_BASED_UNCOND_IO_EXITING; + shadow_cntrl &= ~CPU_BASED_ACTIVATE_IO_BITMAP; + } + else { + /* Use IO_BITMAP in shadow */ + if ( pio_cntrl == 0 ) { + /* + * L1 VMM doesn't intercept IO instruction. + * Use host configuration and reset IO_BITMAP + */ + bitmap = hvm_io_bitmap; + } + else { + /* use IO bitmap */ + bitmap = _shadow_io_bitmap(v); + } + __vmwrite(IO_BITMAP_A, virt_to_maddr(bitmap)); + __vmwrite(IO_BITMAP_B, virt_to_maddr(bitmap) + PAGE_SIZE); + } + + __vmwrite(CPU_BASED_VM_EXEC_CONTROL, shadow_cntrl); +} + +void nvmx_update_secondary_exec_control(struct vcpu *v, + unsigned long value) +{ + set_shadow_control(v, SECONDARY_VM_EXEC_CONTROL, value); +} + +void nvmx_update_exception_bitmap(struct vcpu *v, unsigned long value) +{ + set_shadow_control(v, EXCEPTION_BITMAP, value); +} + static void __clear_current_vvmcs(struct vcpu *v) { struct nestedvcpu *nvcpu = &vcpu_nestedhvm(v); diff --git a/xen/include/asm-x86/hvm/vmx/vvmx.h b/xen/include/asm-x86/hvm/vmx/vvmx.h index 35a184b320..840039c649 100644 --- a/xen/include/asm-x86/hvm/vmx/vvmx.h +++ b/xen/include/asm-x86/hvm/vmx/vvmx.h @@ -161,5 +161,10 @@ int nvmx_handle_vmwrite(struct cpu_user_regs *regs); int nvmx_handle_vmresume(struct cpu_user_regs *regs); int nvmx_handle_vmlaunch(struct cpu_user_regs *regs); +void nvmx_update_exec_control(struct vcpu *v, u32 value); +void nvmx_update_secondary_exec_control(struct vcpu *v, + unsigned long value); +void nvmx_update_exception_bitmap(struct vcpu *v, unsigned long value); + #endif /* __ASM_X86_HVM_VVMX_H__ */ -- 2.30.2